// XPCOMの定数の定義

const kSCHEME = "xmpp";
const kPROTOCOL_NAME = "XMPP Protocol";
const kPROTOCOL_CONTRACTID = "@mozilla.org/network/protocol;1?name=" + kSCHEME;
const kPROTOCOL_CID = Components.ID("f6cb8fd0-ef54-11dd-ba2f-0800200c9a67");
/* 訳注：↑のUUID（GUID）はこのままコピペせず、
 実装したいプロトコルごとに新しく生成すること。 */

// Mozillaによって元々定義されている物
const kSIMPLEURI_CONTRACTID = "@mozilla.org/network/simple-uri;1";
const kIOSERVICE_CONTRACTID = "@mozilla.org/network/io-service;1";
const nsISupports = Components.interfaces.nsISupports;
const nsIIOService = Components.interfaces.nsIIOService;
const nsIProtocolHandler = Components.interfaces.nsIProtocolHandler;
const nsIURI = Components.interfaces.nsIURI;

// TestModuleの定義
/**
 * JavaScriptによるXPCOMコンポーネントを登録するためのあれこれ
 *
 * 私たちはxpcom-startupカテゴリを監視するために、私たち自身をセットアップします。
 * これは私たちに出発点を提供します。
 */

var TestModule = new Object();

TestModule.registerSelf = function (compMgr, fileSpec, location, type)
{
  compMgr = compMgr.QueryInterface(Components.interfaces.nsIComponentRegistrar);
  compMgr.registerFactoryLocation(kPROTOCOL_CID,
                                  kPROTOCOL_NAME,
                                  kPROTOCOL_CONTRACTID,
                                  fileSpec,
                                  location,
                                  type);
};

TestModule.getClassObject = function (compMgr, cid, iid)
{
  if (!cid.equals(kPROTOCOL_CID))
    throw Components.results.NS_ERROR_NO_INTERFACE;

  if (!iid.equals(Components.interfaces.nsIFactory))
    throw Components.results.NS_ERROR_NOT_IMPLEMENTED;

  return ProtocolFactory;
};

TestModule.canUnload = function (compMgr)
{
  return true;
};

function NSGetModule(){
  return TestModule;
}

// ProtocolFactoryの定義

var ProtocolFactory = new Object();

ProtocolFactory.createInstance = function (outer, iid)
{
  if (outer != null)
    throw Components.results.NS_ERROR_NO_AGGREGATION;

  if (!iid.equals(nsIProtocolHandler) && !iid.equals(nsISupports))
    throw Components.results.NS_ERROR_NO_INTERFACE;

  return new Protocol();
};

// Protocolの定義

function Protocol()
{
}

Protocol.prototype =
  {
    QueryInterface: function(iid)
    {
      if (!iid.equals(nsIProtocolHandler) &&
          !iid.equals(nsISupports))
        throw Components.results.NS_ERROR_NO_INTERFACE;
      return this;
    },

    scheme: kSCHEME,
    defaultPort: -1,
    protocolFlags: nsIProtocolHandler.URI_NORELATIVE |
      nsIProtocolHandler.URI_NOAUTH,

    allowPort: function(port, scheme)
    {
      return false;
    },

    newURI: function(spec, charset, baseURI)
    {
      var uri = Components.classes[kSIMPLEURI_CONTRACTID].createInstance(nsIURI);
      uri.spec = spec;
      return uri;
    },

    newChannel: function(aURI)
    {
      // aURIはnsIURIのオブジェクトなので、.specから文字列を得ることができる
      var mySearchTerm = aURI.spec;

      // kSCHEME: の部分を除去する
      mySearchTerm = mySearchTerm.substring(mySearchTerm.indexOf(":") + 1, mySearchTerm.length);
      mySearchTerm = encodeURI(mySearchTerm);

      dump("[mySearchTerm=" + mySearchTerm + "]\n");
      var windowManager = Components.classes['@mozilla.org/appshell/window-mediator;1']
                              .getService(Components.interfaces.nsIWindowMediator);
      var target_window = windowManager.getMostRecentWindow('xmpp:xmppweb');
      target_window.xmpp_go(mySearchTerm);
      /* ダミーのnsIChannelのインスタンスを生成 */
      var ios = Components.classes[kIOSERVICE_CONTRACTID]
        .getService(nsIIOService);

      return ios.newChannel('about:blank', null, null);

    }
  };
